#pragma once

#include <iostream>
#include <vector>
#include <stdint.h>
#include <assert.h>
#include <string.h>

#define INF 0
#define DBG 1
#define ERR 2
#define LOG_LEVEL INF

//日志宏
#define LOG(LEVEL,format, ...) do{\
    if(LEVEL < LOG_LEVEL) break;\
    time_t t = time(nullptr);\
    struct tm* ltm = localtime(&t);\
    char tmp[32] = {0};\
    strftime(tmp,31,"%H:%M:%S",ltm);\
    fprintf(stdout,"[%p %s %s:%d] " format "\n",(void*)pthread_self(),tmp,__FILE__,__LINE__,##__VA_ARGS__);\
}while(0)

#define INF_LOG(format, ...) LOG(INF,format,##__VA_ARGS__)
#define DBG_LOG(format, ...) LOG(DBG,format,##__VA_ARGS__)
#define ERR_LOG(format, ...) LOG(ERR,format,##__VA_ARGS__)

const uint64_t BUFFER_DEFAULT_SIZE = 1024; 
class Buffer
{
private:
    std::vector<char> _buffer;//使用vector进行内存空间管理
    uint64_t _reader_idx;//读偏移
    uint64_t _write_idx;//写偏移

public:
    Buffer()
        :_reader_idx(0)
        ,_write_idx(0)
        ,_buffer(BUFFER_DEFAULT_SIZE)
    {}

    char* Begin(){ return &*_buffer.begin(); }
    //获取当前写入起始地址
    char* WritePosition()
    {
        return Begin() + _write_idx;
    }
    //获取当前读取起始地址
    char* ReadPosition()
    {
        return Begin() + _reader_idx;
    }
    //获取缓冲区末尾空闲空间大小
    uint64_t TailIdleSize()
    {
        return _buffer.size() - _write_idx;
    }
    //获取缓冲区起始空闲空间大小
    uint64_t HeadIdleSize()
    {
        return _reader_idx;
    }
    //获取可读数据大小
    uint64_t ReadAbleSize()
    {
        return _write_idx - _reader_idx;
    }
    //将读偏移向后移动
    void MoveReadOffset(uint64_t len)
    {
        if(len == 0) return;
        //必须小于可读空间大小
        assert(ReadAbleSize() >= len);
        _reader_idx += len;
    }
    //将写偏移向后移动
    void MoveWriteOffset(uint64_t len)
    {
        //必须小于尾部空间大小
        assert(TailIdleSize() >= len);
        _write_idx += len;
    }
    //确保可写空间足够len
    void EnsureWriteSpace(uint64_t len)
    {
        //尾部空间够，直接返回
        if(TailIdleSize() >= len) return;
        //总体空间够，将数据平移到最开始，为后面腾位置
        if(TailIdleSize() + HeadIdleSize() >= len)
        {
            //保存一下可读数据大小
            uint64_t rsz = ReadAbleSize();
            std::copy(ReadPosition(),ReadPosition() + rsz,Begin());//可读数据拷贝到起始位置
            _reader_idx = 0;
            _write_idx = rsz;
        }
        //不够，扩容
        else
        {
            _buffer.resize(_write_idx + len);
        }
    }
    //写入数据
    void Write(const void* date,uint64_t len)
    {
        //保证空间足够
        if(len == 0) return;
        EnsureWriteSpace(len);
        //将数据拷贝进去
        const char* d = (const char*)date;
        std::copy(d,d + len,WritePosition());
    }
    //写入数据并且更新写指针
    void WriteAndPush(const void* date,uint64_t len)
    {
        Write(date,len);
        MoveWriteOffset(len);
    }
    //写入一个字符串
    void WriteString(const std::string& date)
    {
        Write(date.c_str(),date.size());
    }
    //写入一个字符串并且更新写指针
    void WriteStringAndPush(const std::string& date)
    {
        WriteString(date);
        MoveWriteOffset(date.size());
    }
    //写入一个Buffer
    void WriteBuffer(Buffer& date)
    {
        Write(date.ReadPosition(),date.ReadAbleSize());
    }
    //写入一个Buffer并且更新写指针
    void WriteBufferAndPush(Buffer& date)
    {
        Write(date.ReadPosition(),date.ReadAbleSize());
        MoveWriteOffset(date.ReadAbleSize());
    }
    //读取数据
    void Read(void* buf,uint64_t len)
    {
        //获取数据的长度必须小于可读数据
        assert(len <= ReadAbleSize());
        std::copy(ReadPosition(),ReadPosition() + len,(char*)buf);
    }
    //读取数据并且更新读指针
    void ReadAndPop(void* buf,uint64_t len)
    {
        Read(buf,len);
        MoveReadOffset(len);
    }
    //读取一个长度为len的字符串
    std::string ReadString(uint64_t len)
    {
        assert(len <= ReadAbleSize());
        std::string str;
        str.resize(len);
        Read(&str[0],len);
        return str;
    }
    //读取一个长度为len的字符串并且更新读指针
    std::string ReadStringAndPop(uint64_t len)
    {
        assert(len <= ReadAbleSize());
        std::string str = ReadString(len);
        MoveReadOffset(len);
        return str;
    }

    //查找换行符
    char* FindCRLF()
    {
        char* res = (char*)memchr(ReadPosition(),'\n',ReadAbleSize());
        return res;
    }

    //获取一行字符串
    std::string GetLine()
    {
        //找到换行符位置
        char* pos = FindCRLF();
        if(pos == nullptr) return "";
        //+1是为了把换行符也取出来
        return ReadString(pos - ReadPosition() + 1);
    }
    //获取一行字符串并且更新读指针
    std::string GetLineAndPop()
    {
        std::string str = GetLine();
        MoveReadOffset(str.size());
        return str;
    }
    //清空缓冲区
    void Clear()
    {
        //偏移量归零
        _reader_idx = _write_idx = 0;
    }
};